package jpaperwork.meta.transformer;


import jpaperwork.meta.descriptor.*;
import jpaperwork.meta.transformer.path.Path;
import jpaperwork.utils.ReflectionUtils;

import java.util.List;

/**
 * User: fleipold
 * Date: Jul 24, 2009
 * Time: 4:18:35 PM
 */
public class BeanFormBuilder implements FormBuilder {
    public Object buildFlat(Path path, Flat flat, Object transformee) {
        return transformee;
    }

    public Object buildForm(Path path, Form form, List<FieldValue> transformedFields) {
        try {
            Object bean = form.getDecoration(ClassFormDecoration.class).getClazz().newInstance();
             for (FieldValue fieldValue : transformedFields){
                set(bean, fieldValue.getField().getName(), fieldValue.getValue());
             }

            return bean;
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public Object buildCollection(Path path, Aggregation aggregation, List transformedValues) {
        return transformedValues;
    }

    public Object buildPolymorhpic(Path path, Polymorphism polymorphism, DiscriminatedType actualType, Object transformedValue) {
        return transformedValue;
    }


    public void set(Object form, String fieldName, Object value) {
        final Class<? extends Object> formClazz = form.getClass();
        
        if (value == null){
            return;
        }
        try {
            java.lang.reflect.Field field = ReflectionUtils.getDeclaredField(formClazz, fieldName);

            if (  ! field.getType().isAssignableFrom(value.getClass())){
                throw new RuntimeException("Cannot assign value of type "
                        + value.getClass().getName() + " to field of type "
                        +field.getType().getName() +
                " \nfor field  " + fieldName + "\nValue:" + value);
            }
            field.setAccessible(true);
            field.set(form, value);

        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

}
